package rest

import (
	"errors"
	"github.com/gin-gonic/gin"
	"github.com/go-playground/validator/v10"
	"github.com/sirupsen/logrus"
	"monoblog/common"
	"monoblog/domain/auth"
	"monoblog/domain/dto"
	"monoblog/domain/model"
	"monoblog/domain/service"
)

/*
文章接口
*/

// ArticleSave 保存文章(新增或更新)
func ArticleSave(ctx *gin.Context) {
	var form dto.ArticleReqForm
	if err := ctx.ShouldBind(&form); err != nil {
		common.Fail(ctx, "Body数据绑定失败", err)
		return
	}
	//初始化校验器并执行字段校验
	validate := validator.New()
	if err := validate.Struct(form); err != nil {
		common.Fail(ctx, "参数校验失败", err)
		return
	}

	if user, ok := ctx.Get("user"); ok {
		form.LoginUser = user.(*auth.LoginUser)
	} else {
		common.Fail(ctx, "用户未登录", errors.New("user not login"))
		return
	}

	var err error
	id := ctx.Param("id")
	if id == "" {
		id, err = service.GetArticleService().Add(ctx, form)
	} else {
		err = service.GetArticleService().UpdateByID(ctx, id, form)
	}

	if err != nil {
		common.Fail(ctx, "保存文章失败", err)
		return
	}
	//fmt.Println("文本内容\n", form.Content)
	common.Success(ctx, id)
}

// ArticleDelete 删除文章
func ArticleDelete(ctx *gin.Context) {
	id := ctx.Param("id")
	err := service.GetArticleService().DeleteByID(ctx, id)
	if err != nil {
		common.Fail(ctx, "删除文章失败", err)
		return
	}
	common.Success(ctx, nil)
}

// ArticleListByUser 查询用户的文章列表
func ArticleListByUser(ctx *gin.Context) {
	var userId string // 用户ID

	if user, ok := ctx.Get("user"); ok {
		userId = user.(*auth.LoginUser).UID
	} else {
		common.Fail(ctx, "用户未登录", errors.New("user not login"))
		return
	}

	var query common.BaseQuery
	if err := ctx.ShouldBindQuery(&query); err != nil {
		common.Fail(ctx, "Query数据绑定失败", err)
		return
	}

	list, err := service.GetArticleService().FindListByUser(ctx, userId, query)
	if err != nil {
		common.Fail(ctx, "查询用户的文章列表失败", err)
		return
	}

	common.Success(ctx, list)
}

// BlogsBySection 查询专栏已发布的文章列表
func BlogsBySection(ctx *gin.Context) {
	var query common.BaseQuery
	if err := ctx.ShouldBindQuery(&query); err != nil {
		common.Fail(ctx, "Query数据绑定失败", err)
		return
	}

	sectionId := ctx.Query("section") //专栏ID

	if sectionId == "" {
		common.Fail(ctx, "参数错误", errors.New("section is required"))
		return
	}

	list, err := service.GetArticleService().BlogsBySection(ctx, sectionId, query)
	if err != nil {
		common.Fail(ctx, "查询专栏的已发布文章列表失败", err)
		return
	}
	common.Success(ctx, list)
}

// PubBlogsByUser 查询用户或专栏已发布的文章列表
func PubBlogsByUser(ctx *gin.Context) {
	var query common.BaseQuery
	if err := ctx.ShouldBindQuery(&query); err != nil {
		common.Fail(ctx, "Query数据绑定失败", err)
		return
	}

	userId := ctx.Query("userId")     //用户ID
	sectionId := ctx.Query("section") //专栏ID

	var err error
	var list []*model.Article
	if sectionId != "" {
		list, err = service.GetArticleService().BlogsBySection(ctx, sectionId, query)
		if err != nil {
			common.Fail(ctx, "查询专栏的已发布文章列表失败", err)
			return
		}
	} else if userId != "" {
		list, err = service.GetArticleService().BlogsByUser(ctx, userId, query)
		if err != nil {
			common.Fail(ctx, "查询用户的已发布文章列表失败", err)
			return
		}
	}
	common.Success(ctx, list)
}

// ArticleFindById 查询文章详情（即提供给自己查看详情）
func ArticleFindById(ctx *gin.Context) {
	id := ctx.Param("id")
	article, err := service.GetArticleService().FindByID(ctx, id)
	if err != nil {
		common.Fail(ctx, "查询文章失败", err)
		return
	}
	common.Success(ctx, article)
}

// ArticlePublish 发布文章
func ArticlePublish(ctx *gin.Context) {
	id := ctx.Param("id")

	var form dto.ArticleReqPublishForm
	if err := ctx.ShouldBind(&form); err != nil {
		common.Fail(ctx, "Body数据绑定失败", err)
		return
	}
	//初始化校验器并执行字段校验
	validate := validator.New()
	if err := validate.Struct(form); err != nil {
		common.Fail(ctx, "参数校验失败", err)
		return
	}

	if user, ok := ctx.Get("user"); ok {
		form.LoginUser = user.(*auth.LoginUser)
	} else {
		common.Fail(ctx, "用户未登录", errors.New("user not login"))
		return
	}

	err := service.GetArticleService().Publish(ctx, id, form)
	if err != nil {
		logrus.Warnf("[aid: %s] 发布文章失败.  %v", ctx.Value("aid"), err.Error())
		common.Fail(ctx, "发布文章失败", err)
		return
	}
	common.Success(ctx, nil)
}

// ArticleReadById 阅读文章时查询文章详情（即提供给前端阅读文章）
func ArticleReadById(ctx *gin.Context) {
	id := ctx.Param("id")

	article, err := service.GetArticleService().ReadById(ctx, id, false)
	if err != nil {
		common.Fail(ctx, "查询文章失败", err)
		return
	}
	common.Success(ctx, article)
}
